package com.ruoyi.charge.pay.wxpay.controller;


import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.ruoyi.charge.domain.*;
import com.ruoyi.charge.mapper.*;
import com.ruoyi.charge.pay.wxpay.req.WXOrderCreateReq;
import com.ruoyi.charge.service.ICashProportionService;
import com.ruoyi.charge.service.IRecordService;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.CommissionType;
import com.ruoyi.common.enums.DeletedStatus;
import com.ruoyi.common.utils.XmlUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import jodd.util.ObjectUtil;
import lombok.AllArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.validation.Validation;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;


/**
 * @author Binary Wang
 */
@Api("微信支付")
@RestController
@RequestMapping("/charge/pay/wx")
@AllArgsConstructor
public class WxPayController {

    private static final Logger logger = LoggerFactory.getLogger(WxPayController.class);

    @Autowired
    private WxPayService wxService;
    @Autowired
    private IRecordService iRecordService;
    @Autowired
    private ICashProportionService cashProportionService;

    @Autowired
    private RecordMapper recordMapper;
    @Autowired
    private WxUserMapper wxUserMapper;
    @Autowired
    private StoreMapper storeMapper;
    @Autowired
    private CommissionRecordMapper commissionRecordMapper;
    @Autowired
    private AgentMapper agentMapper;
    @Autowired
    private AgentRMapper agentRMapper;


    /**
     * 微信小程序支付下单
     */
    @ApiOperation("微信小程序支付")
    @PostMapping("/createOrder")
    public AjaxResult createOrder(@RequestBody WXOrderCreateReq req) throws WxPayException {

        logger.error("进入微信支付！！！！！！！！！！！！！！！！！！！！！！！！");
        //创建订单信息
        String openid = req.getOpenid();
        Long storeId = req.getStoreId();
        WxUser wxUser = wxUserMapper.selectOne(
                new LambdaQueryWrapper<WxUser>()
                        .eq(WxUser::getOpenid, openid)
                        .eq(WxUser::getDeleted, DeletedStatus.VALID.getCode())
                        .last("limit 1")
        );
        if (wxUser == null) {
            logger.error("微信app支付下单失败，openid不存在 openid：" + openid);
            return AjaxResult.error("支付失败！");
        }
        Long userId = wxUser.getWxUserId();
        //充电记录
        Record record = new Record();
        record.setUserId(userId);
        record.setStoreId(storeId);
        Store store = storeMapper.selectOne(
                new LambdaQueryWrapper<Store>().eq(Store::getStoreId, storeId)
                        .eq(Store::getDeleted, DeletedStatus.VALID.getCode())
                        .last("limit 1")
        );
        if (store == null) {
            logger.error("微信app支付下单失败，storeId不存在 storeId：" + storeId);
            return AjaxResult.error("支付失败！");
        }
        record.setStoreName(store.getStoreName());
        record.setStoreNumber(store.getNumber());
        record.setAvatarUrl(store.getAvatarUrl());
        record.setEquipmentNumber(req.getEquipmentNumber());
        record.setTableNumber(req.getTableNumber());
        Integer fee = req.getFee();
        BigDecimal feeBigDecimal = new BigDecimal(fee.toString());
        record.setFee(feeBigDecimal);
        Integer allowTime = req.getAllowTime();
        record.setAllowTime(allowTime);
        String chargeStr = this.getBuleToothChargeStr(allowTime);
        record.setRemark(chargeStr);
        iRecordService.save(record);
        Long recordId = record.getId();
        //调用微信下单
        WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
        request.setOutTradeNo(recordId.toString());
        request.setTotalFee(req.getFee());
        request.setOpenid(openid);
        //ip
        request.setBody("充电-微信小程序支付");
        request.setSpbillCreateIp("118.190.148.198");
        request.setNotifyUrl("http://118.190.148.198/prod-api/charge/pay/wx/notify/order");
        request.setTradeType("JSAPI");
        WxPayMpOrderResult map = this.wxService.createOrder(request);
        //封装返回数据
        Map<String, String> result = new HashMap<>();
        result.put("recordId", recordId.toString());
        result.put("paySign", map.getPaySign());
        result.put("signType", map.getSignType());
        result.put("appid", map.getAppId());
        result.put("package", map.getPackageValue());
        result.put("timeStamp", map.getTimeStamp());
        result.put("nonceStr", map.getNonceStr());
        logger.error("下单成功：{}, map:{}", JSONObject.toJSONString(result), JSONObject.toJSONString(map));
        return AjaxResult.success(result);
    }

    private String getBuleToothChargeStr(Integer allowTime) {
        String strPre = "FE D5 ";
        String strPost = " 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 45";
        if(allowTime>=60){
            Integer hour = allowTime/60;
            String hourStr = hour.toString();
            if(hourStr.length()==1){
                hourStr = "0" + hourStr;
            }
            Integer minute = allowTime%60;
            String minuteStr = minute.toString();
            if (minuteStr.length() == 1){
                minuteStr = "0" + minuteStr;
            }
            strPre += hourStr+" "+minuteStr;
        }else {
            String minuteStr = allowTime.toString();
            if (minuteStr.length() == 1){
                minuteStr = "0" + minuteStr;
            }
            strPre += "00 " + minuteStr;
        }
        strPre += strPost;
        return strPre;
    }

    @GetMapping("/test/chargeStr")
    public AjaxResult<Void> getChargeStr(Integer time){
        String str = this.getBuleToothChargeStr(time);
        return AjaxResult.success(str);
    }

    /**
     * 微信支付回调
     *
     * @param xmlData
     * @return
     * @throws WxPayException
     */
    @ApiOperation(value = "支付回调通知处理")
    @PostMapping("/notify/order")
    public String parseOrderNotifyResult(@RequestBody String xmlData) throws WxPayException {
        logger.error("进入微信支付回调");
        try {
            System.out.println(xmlData);
            Map<String, String> stringMap = XmlUtil.xml2Map(xmlData);

            System.out.println(stringMap.toString());
            logger.error("微信支付回调返回：{}", JSONObject.toJSONString(stringMap));
            //判断订单是否成功完成
            if ("SUCCESS".equals(stringMap.get("/xml/result_code"))) {
                //成功
                logger.error("微信支付回调   成功！！！！！！！！！！");
                String outTrageNo = stringMap.get("/xml/out_trade_no");
                Long recordId = Long.valueOf(outTrageNo);
                Record record = recordMapper.selectById(recordId);
                Record update = new Record();
                update.setId(recordId);
                update.setStatus(1);
                recordMapper.updateById(update);
                generateCommissionRecord(record);

                return WxPayNotifyResponse.success("成功");
            } else {
                logger.error("微信支付回调   失败！！！！！！！！！！");
                return WxPayNotifyResponse.fail("失败");
            }
        } catch (Exception e) {
            logger.error("微信支付回调失败：{}", e.getMessage(), e);
            return WxPayNotifyResponse.fail("失败");
        }

    }

    @GetMapping("/test/generate/commission")
    public AjaxResult<Void> generateTest(@RequestParam("recordId") Long recordId) {

        Record record = recordMapper.selectById(recordId);
        Record update = new Record();
        update.setId(recordId);
        update.setStatus(1);
        recordMapper.updateById(update);


        //todo 生成分佣记录
        generateCommissionRecord(record);
        return AjaxResult.success();
    }

    private void generateCommissionRecord(Record record) {
        Long recordId = record.getId();
        //店铺
        Long storeId = record.getStoreId();
        Store store = storeMapper.selectOne(
                new LambdaQueryWrapper<Store>().eq(Store::getStoreId, storeId)
                        .eq(Store::getDeleted, DeletedStatus.VALID.getCode())
                        .last("limit 1")
        );
        //费用
        BigDecimal fee = record.getFee();

        //层级分佣
        //店铺
        BigDecimal storeProportion = cashProportionService.getStoreProportion();
        CommissionRecord storeCommissionRecord = new CommissionRecord();
        storeCommissionRecord.setRecordId(recordId);
        storeCommissionRecord.setFee(fee);
        storeCommissionRecord.setStoreId(storeId);
        storeCommissionRecord.setStoreName(store.getStoreName());
        storeCommissionRecord.setStoreNumber(store.getNumber());
        storeCommissionRecord.setStoreAvatarUrl(store.getAvatarUrl());
        storeCommissionRecord.setProportion(storeProportion);
        storeCommissionRecord.setLast(1);
        BigDecimal storeCommission = fee.multiply(storeProportion);
        storeCommissionRecord.setCommission(storeCommission);
        storeCommissionRecord.setType(CommissionType.STORE.getCode());

        //区级
        BigDecimal districtProportion = cashProportionService.getDistrictProportion();
        //市级
        BigDecimal cityProportion = cashProportionService.getCityProportion();
        //省级
        BigDecimal provinceProportion = cashProportionService.getProvinceProportion();
        Long firstAgentId = store.getAgentId();
        if (firstAgentId != null && firstAgentId != 0) {
            Agent firstAgent = this.getAgentInfoById(firstAgentId);
            if (firstAgent.getType().equals(CommissionType.DISTRICT.getCode())) {
                if (firstAgent.getProportion() != null && firstAgent.getProportion().compareTo(BigDecimal.ZERO) > 0) {
                    districtProportion = firstAgent.getProportion();
                }
                CommissionRecord firstAgentCommssionRecord = new CommissionRecord();
                firstAgentCommssionRecord.setRecordId(recordId);
                firstAgentCommssionRecord.setFee(fee);
                firstAgentCommssionRecord.setType(CommissionType.DISTRICT.getCode());
                firstAgentCommssionRecord.setProportion(districtProportion);
                firstAgentCommssionRecord.setAgentId(firstAgentId);
                firstAgentCommssionRecord.setAgentNumber(firstAgent.getAgentNumber());
                firstAgentCommssionRecord.setAgentAvatarUrl(firstAgent.getAvatarUrl());
                BigDecimal districtCommission = fee.multiply(districtProportion);
                BigDecimal realCommission = districtCommission.subtract(storeCommission);
                if (realCommission.compareTo(BigDecimal.ZERO) == -1) {
                    logger.error("代理商分佣比店铺低，数据出错，充电记录id:{}, 店铺id:{}, 代理商id:{}, 店铺分佣:{}, 代理商分佣:{}", recordId, storeId, firstAgentId, storeCommission, districtCommission);
                } else {
                    firstAgentCommssionRecord.setCommission(realCommission);
                }
                AgentR agentR = this.getAgentRInfoByChildId(firstAgentId);
                if (agentR != null) {
                    //市级
                    Long secondAgentId = agentR.getAgentId();
                    Integer secondAgentCode = agentR.getAgentCode();
                    Agent secondAgent = this.getAgentInfoById(secondAgentId);
                    CommissionRecord secondCommissionRecord = new CommissionRecord();
                    secondCommissionRecord.setRecordId(recordId);
                    secondCommissionRecord.setFee(fee);
                    secondCommissionRecord.setAgentId(secondAgentId);
                    secondCommissionRecord.setAgentNumber(secondAgent.getAgentNumber());
                    secondCommissionRecord.setAgentAvatarUrl(secondAgent.getAvatarUrl());
                    if (secondAgent.getType().equals(CommissionType.CITY.getCode())) {
                        if (secondAgent.getProportion() != null && secondAgent.getProportion().compareTo(BigDecimal.ZERO) > 0){
                            cityProportion = secondAgent.getProportion();
                        }
                        secondCommissionRecord.setProportion(cityProportion);
                        BigDecimal cityCommission = fee.multiply(cityProportion);
                        BigDecimal secondRealCommission = cityCommission.subtract(districtCommission);
                        if (secondRealCommission.compareTo(BigDecimal.ZERO) == -1) {
                            logger.error("代理商分佣出错，充电记录id:{}, 上级代理商id:{}, 下级代理商id:{}, 上级分佣:{}, 下级分佣:{}", recordId, secondAgentId, firstAgentId, cityCommission, districtCommission);
                        } else {
                            secondCommissionRecord.setCommission(secondRealCommission);
                        }
                        secondCommissionRecord.setType(CommissionType.CITY.getCode());
                        AgentR secondAgnetR = this.getAgentRInfoByChildId(secondAgentId);
                        if (secondAgnetR != null) {
                            //省级
                            Long thirdAgentId = secondAgnetR.getAgentId();
                            Agent thirdAgent = this.getAgentInfoById(thirdAgentId);
                            CommissionRecord thirdCommissionRecord = new CommissionRecord();
                            thirdCommissionRecord.setRecordId(recordId);
                            thirdCommissionRecord.setFee(fee);
                            thirdCommissionRecord.setAgentId(thirdAgentId);
                            thirdCommissionRecord.setAgentNumber(thirdAgent.getAgentNumber());
                            thirdCommissionRecord.setAgentAvatarUrl(thirdAgent.getAvatarUrl());
                            if (thirdAgent.getProportion() != null && thirdAgent.getProportion().compareTo(BigDecimal.ZERO)>0 ) {
                                provinceProportion = thirdAgent.getProportion();
                            }
                            thirdCommissionRecord.setProportion(provinceProportion);
                            BigDecimal provinceCommission = fee.multiply(provinceProportion);
                            BigDecimal thirdRealCommission = provinceCommission.subtract(cityCommission);
                            thirdCommissionRecord.setCommission(thirdRealCommission);
                            thirdCommissionRecord.setFirst(1);
                            thirdCommissionRecord.setType(CommissionType.PROVINCE.getCode());
                            commissionRecordMapper.insert(thirdCommissionRecord);
                        } else {
                            secondCommissionRecord.setFirst(1);
                        }
                        commissionRecordMapper.insert(secondCommissionRecord);
                    } else {
                        //省级
                        if (secondAgent.getProportion() != null && secondAgent.getProportion().compareTo(BigDecimal.ZERO)>0 ) {
                            provinceProportion = secondAgent.getProportion();
                        }
                        BigDecimal provinceCommission = fee.multiply(provinceProportion);
                        BigDecimal secondRealCommission = provinceCommission.subtract(districtCommission);
                        if (secondRealCommission.compareTo(BigDecimal.ZERO) == -1) {
                            logger.error("代理商分佣出错，充电记录id:{}, 上级代理商id:{}, 下级代理商id:{}, 上级分佣:{}, 下级分佣:{}", recordId, secondAgentId, firstAgentId, provinceCommission, districtCommission);
                        } else {
                            secondCommissionRecord.setCommission(secondRealCommission);
                        }
                        secondCommissionRecord.setType(CommissionType.PROVINCE.getCode());
                        secondCommissionRecord.setFirst(1);
                        commissionRecordMapper.insert(secondCommissionRecord);
                    }
                } else {
                    firstAgentCommssionRecord.setFirst(1);
                }
                commissionRecordMapper.insert(firstAgentCommssionRecord);

            } else if (firstAgent.getType().equals(CommissionType.CITY.getCode())) {
                if (firstAgent.getProportion() != null && firstAgent.getProportion().compareTo(BigDecimal.ZERO)>0 ) {
                    cityProportion = firstAgent.getProportion();
                }
                CommissionRecord firstAgentCommssionRecord = new CommissionRecord();
                firstAgentCommssionRecord.setRecordId(recordId);
                firstAgentCommssionRecord.setFee(fee);
                firstAgentCommssionRecord.setType(CommissionType.DISTRICT.getCode());
                firstAgentCommssionRecord.setProportion(cityProportion);
                firstAgentCommssionRecord.setAgentId(firstAgentId);
                firstAgentCommssionRecord.setAgentNumber(firstAgent.getAgentNumber());
                firstAgentCommssionRecord.setAgentAvatarUrl(firstAgent.getAvatarUrl());
                BigDecimal cityCommission = fee.multiply(cityProportion);
                BigDecimal realCommission = cityCommission.subtract(storeCommission);
                if (realCommission.compareTo(BigDecimal.ZERO) == -1) {
                    logger.error("代理商分佣比店铺低，数据出错，充电记录id:{}, 店铺id:{}, 代理商id:{}, 店铺分佣:{}, 代理商分佣:{}", recordId, storeId, firstAgentId, storeCommission, cityCommission);
                } else {
                    firstAgentCommssionRecord.setCommission(realCommission);
                }
                AgentR agentR = this.getAgentRInfoByChildId(firstAgentId);
                if (agentR != null) {
                    //省级
                    Long thirdAgentId = agentR.getAgentId();
                    Agent thirdAgent = this.getAgentInfoById(thirdAgentId);
                    CommissionRecord thirdCommissionRecord = new CommissionRecord();
                    thirdCommissionRecord.setRecordId(recordId);
                    thirdCommissionRecord.setFee(fee);
                    thirdCommissionRecord.setAgentId(thirdAgentId);
                    thirdCommissionRecord.setAgentNumber(thirdAgent.getAgentNumber());
                    thirdCommissionRecord.setAgentAvatarUrl(thirdAgent.getAvatarUrl());
                    if (thirdAgent.getProportion() != null && thirdAgent.getProportion().compareTo(BigDecimal.ZERO)>0 ) {
                        provinceProportion = thirdAgent.getProportion();
                    }
                    thirdCommissionRecord.setProportion(provinceProportion);
                    BigDecimal provinceCommission = fee.multiply(provinceProportion);
                    BigDecimal thirdRealCommission = provinceCommission.subtract(cityCommission);
                    thirdCommissionRecord.setCommission(thirdRealCommission);
                    thirdCommissionRecord.setFirst(1);
                    thirdCommissionRecord.setType(CommissionType.PROVINCE.getCode());
                    commissionRecordMapper.insert(thirdCommissionRecord);
                } else {
                    firstAgentCommssionRecord.setFirst(1);
                }
                commissionRecordMapper.insert(firstAgentCommssionRecord);
            } else if (firstAgent.getType().equals(CommissionType.PROVINCE.getCode())) {
                //省级
                if (firstAgent.getProportion() != null && firstAgent.getProportion().compareTo(BigDecimal.ZERO)>0 ) {
                    provinceProportion = firstAgent.getProportion();
                }
                CommissionRecord firstAgentCommssionRecord = new CommissionRecord();
                firstAgentCommssionRecord.setRecordId(recordId);
                firstAgentCommssionRecord.setFee(fee);
                firstAgentCommssionRecord.setType(CommissionType.PROVINCE.getCode());
                firstAgentCommssionRecord.setProportion(provinceProportion);
                firstAgentCommssionRecord.setAgentId(firstAgentId);
                firstAgentCommssionRecord.setAgentNumber(firstAgent.getAgentNumber());
                firstAgentCommssionRecord.setAgentAvatarUrl(firstAgent.getAvatarUrl());
                BigDecimal provinceCommission = fee.multiply(provinceProportion);
                BigDecimal realCommission = provinceCommission.subtract(storeCommission);
                if (realCommission.compareTo(BigDecimal.ZERO) == -1) {
                    logger.error("代理商分佣比店铺低，数据出错，充电记录id:{}, 店铺id:{}, 代理商id:{}, 店铺分佣:{}, 代理商分佣:{}", recordId, storeId, firstAgentId, storeCommission, provinceCommission);
                } else {
                    firstAgentCommssionRecord.setCommission(realCommission);
                }
                firstAgentCommssionRecord.setFirst(1);
                firstAgentCommssionRecord.setType(CommissionType.PROVINCE.getCode());
                commissionRecordMapper.insert(firstAgentCommssionRecord);
            }
        }else {
            storeCommissionRecord.setFirst(1);
        }
        commissionRecordMapper.insert(storeCommissionRecord);
    }

    /***
     * 根据childId获取代理商关系信息
     * @param agentId
     * @return
     */
    private AgentR getAgentRInfoByChildId(Long agentId) {
        AgentR agentR = agentRMapper.selectOne(
                new LambdaQueryWrapper<AgentR>().eq(AgentR::getChildId, agentId)
                        .eq(AgentR::getDeleted, DeletedStatus.VALID.getCode())
                        .last("limit 1")
        );
        return agentR;
    }

    /***
     * 根据id获取代理商信息
     * @param agentId
     * @return
     */
    private Agent getAgentInfoById(Long agentId) {
        Agent agent = agentMapper.selectOne(
                new LambdaQueryWrapper<Agent>().eq(Agent::getAgentId, agentId)
                        .eq(Agent::getDeleted, DeletedStatus.VALID.getCode())
                        .last("limit 1")
        );
        return agent;
    }


}

